package repository

import (
	"github.com/gin-gonic/gin"
	"time"
	"yak.admin/src/entity"
	"yak.admin/src/repository"
	"yak.admin/src/service"
	"yak.admin/src/util"
)

type DrugReportRepository struct {
	Page           int    `form:"page"`
	Pagesize       int    `form:"per-page"`
	Id             int    `form:"id"`
	Province       string `form:"Condition[province]"`
	City           string `form:"Condition[city]"`
	County         string `form:"Condition[county]"`
	IsSuper        bool
	YakLst         string `form:"Condition[yak_lst]"`
	YakLstTxt      string `form:"Condition[yak_lst_txt]"`
	YakLstExt      string `form:"Condition[yak_lst_ext]"`
	Status         int    `form:"Condition[status]"`
	Category       int    `form:"Condition[category]"`
	DosageForm     int    `form:"Condition[dosage_form]"`
	Risk           int    `form:"Condition[risk]"`
	YakDt          string `form:"Condition[yak_dt]"`
	YakDtS         string `form:"Condition[yak_dt_s]"`
	YakDtE         string `form:"Condition[yak_dt_e]"`
	SortReportedAt string `form:"Sort[reported_at]"`
	SortCheckedAt  string `form:"Sort[checked_at]"`
	repository.DrugReportRepository
}

func (repository *DrugReportRepository) FindReportView(id uint) map[string]interface{} {
	report := entity.DrugReport{}
	reader := new(service.ReaderQuery).CreateModelQuery(&report).
		WithEQ("id", id).WithPreloads([]string{"Category", "DrugAnnexes"})
	reader.One(&report)
	riskLabels := repository.DrugRiskLabels()
	return reader.Viewlist(&report, func(item interface{}) map[string]interface{} {
		m := item.(*entity.DrugReport)
		annexes := m.DrugAnnexes
		return map[string]interface{}{
			"id":          m.Id,
			"number":      m.Number,
			"title":       m.Title,
			"category":    m.Category.Name,
			"risk":        reader.AsCheckListString(m.RiskRefer, riskLabels),
			"remark":      m.Remark,
			"reported_at": reader.AsDatetime(m.ReportedAt),
			"unit":        m.Unit,
			"address":     m.Address,
			"phone":       m.Phone,
			"imgs":        reader.AsListField(annexes, len(annexes), "Src"),
		}
	})
}

func (repository *DrugReportRepository) FindReports(c *gin.Context) ([]map[string]interface{}, int64) {
	if err := util.DefaultGetValidParams(c, repository); err != nil {
		return []map[string]interface{}{}, 0
	}

	reader := new(service.ReaderQuery).CreateModelQuery(&entity.DrugReport{}).
		WithEQ("status", repository.Status).
		WithPreloads([]string{"Category"}).
		WithYakLst(repository.YakLst, repository.YakLstTxt, repository.YakLstExt).
		WithPCC(repository.Province, repository.City, repository.County, repository.IsSuper).
		WithPage(repository.Page).WithPageSize(repository.Pagesize).
		WithDefaultOrder("reported_at", repository.SortReportedAt, "id", "desc")

	// reader.Debug = true

	var reports []*entity.DrugReport
	reader.Reader(&reports)
	riskLabels := repository.DrugRiskLabels()

	res := reader.Datalist(reports, len(reports), func(index int, item interface{}) map[string]interface{} {
		m := item.(*entity.DrugReport)
		return map[string]interface{}{
			"_serial":     reader.AsSerial(index),
			"id":          m.Id,
			"number":      m.Number,
			"title":       m.Title,
			"category":    m.Category.Name,
			"risk":        reader.AsCheckListString(m.RiskRefer, riskLabels),
			"reported_at": reader.AsDatetime(m.ReportedAt),
			"unit":        m.Unit,
			"address":     m.Address,
			"phone":       m.Phone,
			"remark":      m.Remark,
		}
	})

	return res, reader.Count()
}

func (repository *DrugReportRepository) FindHistoryReports(c *gin.Context, admin entity.Admin) ([]map[string]interface{}, int64) {
	if err := util.DefaultGetValidParams(c, repository); err != nil {
		return []map[string]interface{}{}, 0
	}

	reader := new(service.ReaderQuery).CreateModelQuery(&entity.DrugReport{}).
		WithEQ("status", repository.Status).
		WithIN("status", []int{util.IgnoreStatus, util.FollowStatus}).
		WithEQ("category_refer", repository.Category).
		WithFindInSet("risk_refer", repository.Risk).
		WithPreloads([]string{"Category"}).
		WithYakDtIntDate(repository.YakDt, repository.YakDtS, repository.YakDtE, "2006-01-02").
		WithYakLst(repository.YakLst, repository.YakLstTxt, repository.YakLstExt).
		WithEQ("province", repository.Province).
		WithEQ("city", repository.City).
		WithEQ("county", repository.County).
		WithPCC(admin.Province, admin.City, admin.County, repository.IsSuper).
		WithPage(repository.Page).WithPageSize(repository.Pagesize).
		WithOrder("checked_at", repository.SortCheckedAt).
		WithDefaultOrder("reported_at", repository.SortReportedAt, "id", "desc")

	// reader.Debug = true

	var reports []*entity.DrugReport
	reader.Reader(&reports)
	riskLabels := repository.DrugRiskLabels()
	status := repository.StatusLabels()

	res := reader.Datalist(reports, len(reports), func(index int, item interface{}) map[string]interface{} {
		m := item.(*entity.DrugReport)
		return map[string]interface{}{
			"_serial":      reader.AsSerial(index),
			"id":           m.Id,
			"number":       m.Number,
			"title":        m.Title,
			"category":     m.Category.Name,
			"risk":         reader.AsCheckListString(m.RiskRefer, riskLabels),
			"reported_at":  reader.AsDatetime(m.ReportedAt),
			"unit":         m.Unit,
			"address":      m.Address,
			"phone":        m.Phone,
			"remark":       m.Remark,
			"checked_at":   reader.AsDatetime(m.CheckedAt),
			"status_label": status[m.Status],
			"status":       m.Status,
			"comment":      m.Comment,
		}
	})

	return res, reader.Count()
}

func (repository *DrugReportRepository) FindSummaryReports(c *gin.Context, admin entity.Admin) ([]map[string]interface{}, int64) {
	if err := util.DefaultGetValidParams(c, repository); err != nil {
		return []map[string]interface{}{}, 0
	}

	reader := new(service.ReaderQuery).CreateModelQuery(&entity.DrugReport{}).
		WithEQ("status", util.FollowStatus).
		WithEQ("category_refer", repository.Category).
		WithFindInSet("risk_refer", repository.Risk).
		WithPreloads([]string{"Category"}).
		WithYakDtIntDate(repository.YakDt, repository.YakDtS, repository.YakDtE, "2006-01-02").
		WithYakLst(repository.YakLst, repository.YakLstTxt, repository.YakLstExt).
		WithEQ("province", repository.Province).
		WithEQ("city", repository.City).
		WithEQ("county", repository.County).
		WithPCC(admin.Province, admin.City, admin.County, admin.IsSuper()).
		WithOrder("checked_at", repository.SortCheckedAt).
		WithDefaultOrder("reported_at", repository.SortReportedAt, "id", "desc").
		WithPage(repository.Page).WithPageSize(repository.Pagesize)

	// reader.Debug = true

	var reports []*entity.DrugReport
	reader.Reader(&reports)
	riskLabels := repository.DrugRiskLabels()
	status := repository.StatusLabels()

	res := reader.Datalist(reports, len(reports), func(index int, item interface{}) map[string]interface{} {
		m := item.(*entity.DrugReport)
		return map[string]interface{}{
			"_serial":     reader.AsSerial(index),
			"id":          m.Id,
			"number":      m.Number,
			"title":       m.Title,
			"category":    m.Category.Name,
			"risk":        reader.AsCheckListString(m.RiskRefer, riskLabels),
			"reported_at": reader.AsDatetime(m.ReportedAt),
			"unit":        m.Unit,
			"address":     m.Address,
			"phone":       m.Phone,
			"remark":      m.Remark,
			"checked_at":  reader.AsDatetime(m.CheckedAt),
			"status":      status[m.Status],
			"comment":     m.Comment,
		}
	})

	return res, reader.Count()
}

func (repository *DrugReportRepository) FindHistoryExcel(c *gin.Context, admin entity.Admin) (map[string]interface{}, []map[string]interface{}) {
	if err := util.DefaultGetValidParams(c, repository); err != nil {
		return map[string]interface{}{}, []map[string]interface{}{}
	}

	reader := new(service.ReaderQuery).CreateModelQuery(&entity.DrugReport{}).
		WithEQ("status", repository.Status).
		WithIN("status", []int{util.IgnoreStatus, util.FollowStatus}).
		WithEQ("category_refer", repository.Category).
		WithFindInSet("risk_refer", repository.Risk).
		WithPreloads([]string{"Category"}).
		WithYakDtIntDate(repository.YakDt, repository.YakDtS, repository.YakDtE, "2006-01-02").
		WithYakLst(repository.YakLst, repository.YakLstTxt, repository.YakLstExt).
		WithEQ("province", repository.Province).
		WithEQ("city", repository.City).
		WithEQ("county", repository.County).
		WithPCC(admin.Province, admin.City, admin.County, repository.IsSuper).
		WithOrder("checked_at", repository.SortCheckedAt).
		WithDefaultOrder("reported_at", repository.SortReportedAt, "id", "desc").
		WithPage(1).WithPageSize(50000)

	// reader.Debug = true

	var reports []*entity.DrugReport
	reader.Reader(&reports)
	riskLabels := repository.DrugRiskLabels()
	status := repository.StatusLabels()

	header := map[string]interface{}{
		"_serial":     "序号",
		"number":      "编号",
		"title":       "药品名称",
		"category":    "药品类别",
		"risk":        "风险累及系统-器官",
		"reported_at": "上报时间",
		"unit":        "上报单位",
		"address":     "所属地区",
		"phone":       "联系电话",
		"remark":      "备注",
		"checked_at":  "处理时间",
		"status":      "处理状态",
		"comment":     "风险评价",
		"username":    "上报人",
	}

	res := reader.Datalist(reports, len(reports), func(index int, item interface{}) map[string]interface{} {
		m := item.(*entity.DrugReport)
		return map[string]interface{}{
			"_serial": reader.AsSerial(index),
			//"id":          m.Id,
			"number":      m.Number,
			"title":       m.Title,
			"category":    m.Category.Name,
			"risk":        reader.AsCheckListString(m.RiskRefer, riskLabels),
			"reported_at": reader.AsDatetime(m.ReportedAt),
			"unit":        m.Unit,
			"address":     m.Address,
			"phone":       m.Phone,
			"remark":      m.Remark,
			"checked_at":  reader.AsDatetime(m.CheckedAt),
			"status":      status[m.Status],
			"comment":     m.Comment,
			"username":    m.Username,
		}
	})

	return header, res
}

func (repository *DrugReportRepository) FindSummaryExcel(c *gin.Context, admin entity.Admin) (map[string]interface{}, []map[string]interface{}) {
	if err := util.DefaultGetValidParams(c, repository); err != nil {
		return map[string]interface{}{}, []map[string]interface{}{}
	}

	reader := new(service.ReaderQuery).CreateModelQuery(&entity.DrugReport{}).
		WithEQ("status", util.FollowStatus).
		WithEQ("category_refer", repository.Category).
		WithFindInSet("risk_refer", repository.Risk).
		WithPreloads([]string{"Category"}).
		WithYakDtIntDate(repository.YakDt, repository.YakDtS, repository.YakDtE, "2006-01-02").
		WithYakLst(repository.YakLst, repository.YakLstTxt, repository.YakLstExt).
		WithEQ("province", repository.Province).
		WithEQ("city", repository.City).
		WithEQ("county", repository.County).
		WithPCC(admin.Province, admin.City, admin.County, admin.IsSuper()).
		WithOrder("checked_at", repository.SortCheckedAt).
		WithDefaultOrder("reported_at", repository.SortReportedAt, "id", "desc").
		WithPage(1).WithPageSize(50000)

	// reader.Debug = true

	header := map[string]interface{}{
		"_serial":     "序号",
		"number":      "编号",
		"title":       "药品名称",
		"category":    "药品类别",
		"risk":        "风险累及系统-器官",
		"reported_at": "上报时间",
		"unit":        "上报单位",
		"address":     "所属地区",
		"phone":       "联系电话",
		"remark":      "备注",
		"checked_at":  "处理时间",
		"status":      "处理状态",
		"comment":     "风险评价",
		"username":    "上报人",
	}

	var reports []*entity.DrugReport
	reader.Reader(&reports)
	riskLabels := repository.DrugRiskLabels()

	res := reader.Datalist(reports, len(reports), func(index int, item interface{}) map[string]interface{} {
		m := item.(*entity.DrugReport)
		return map[string]interface{}{
			"_serial": reader.AsSerial(index),
			//"id":          m.Id,
			"number":      m.Number,
			"title":       m.Title,
			"category":    m.Category.Name,
			"risk":        reader.AsCheckListString(m.RiskRefer, riskLabels),
			"reported_at": reader.AsDatetime(m.ReportedAt),
			"unit":        m.Unit,
			"address":     m.Address,
			"phone":       m.Phone,
			"remark":      m.Remark,
			"checked_at":  reader.AsDatetime(m.CheckedAt),
			"comment":     m.Comment,
			"username":    m.Username,
		}
	})

	return header, res
}


// 最近提交
func (repository *DrugReportRepository) PendingReports(c *gin.Context, admin entity.Admin) int64 {
	timeStr := time.Now().Format("2006-01-02")
	t, _ := time.ParseInLocation("2006-01-02", timeStr, time.Local)
	timeNumber := t.Unix()
	// fmt.Println(t.Format("2006-01-02 15:04:05"))
	return new(service.ReaderQuery).CreateModelQuery(&entity.DrugReport{}).
		WithEQ("status", util.PendingStatus).
		WithLTE("reported_at", timeNumber+86400).
		WithGTE("reported_at", timeNumber).
		WithPCC(admin.Province, admin.City, admin.County, admin.IsSuper()).Count()
}
